package nl.project.data.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServlet;

import nl.project.data.Appointment;
import nl.project.data.Enrollment;
import nl.project.data.Parent;
import nl.project.data.Student;
import nl.project.source.Message;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;

/**
 * General DAO for the database.
 * 
 * @author Zerocool, Jeroen
 */
@SuppressWarnings("serial")
public class MembersDAO extends HttpServlet {

	/**
	 * Authenticate the user which is trying to log in. Check the database for
	 * the corresponding code and password.
	 * 
	 * @param id
	 *            , Given login code
	 * @param password
	 * @return boolean, True if authentication went right, else false
	 * @throws EntityNotFoundException
	 *             , if no user was found with the given code, password and type
	 *             combination
	 */
	public static boolean authenticate(int id, String password, String type)
			throws EntityNotFoundException {
		boolean isAllowed = false;
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();
		String capitalType = type;
		for (int i = 0; i < type.length(); i++) {
			if (i == 0) {
				// Capitalize the first letter of the string.
				capitalType = String.format("%s%s",
						Character.toUpperCase(capitalType.charAt(0)),
						capitalType.substring(1));
			}
		}
		Key k = KeyFactory.createKey(capitalType + "s", capitalType + "s");
		Query query = new Query(capitalType, k).addFilter(type + "Id",
				FilterOperator.EQUAL, String.valueOf(id));
		Entity user = datastore.prepare(query).asSingleEntity();

		// Check if user is found. If not, stop authenticate and return to
		// startpage.
		if (user == null) {
			throw new EntityNotFoundException(k);
		}
		if (user.getProperty("password").toString().equals(password)) {
			isAllowed = true;
		}
		return isAllowed;
	}

	/**
	 * 
	 * @return The Entity that has all info with a perticular id
	 * @throws EntityNotFoundException
	 */
	public static Entity getEntityInfo(int id, Key key, String property,
			String kind) throws EntityNotFoundException {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();
		// <important>(last argument)-> since addFilter() accepts Object, it is
		// necessary that you take the STRING value
		// it won't work without it!!! </important>
		
		Query query = new Query(kind, key).addFilter(property,
				FilterOperator.EQUAL, String.valueOf(id));
		Entity entity = datastore.prepare(query).asSingleEntity();
		if (entity == null) {
			throw new EntityNotFoundException(key);
		}
		return entity;
	}

	/**
	 * Dit moet uit datastore gehaald worden die door de jsp na inloggen van een
	 * ouder en keuze heeft gemaakt welke ouder hij wil spreken zou die data
	 * hier wil opgehaald moeten worden.
	 * 
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static ArrayList<Enrollment> getEnrollments() {
		DatastoreService d = DatastoreServiceFactory.getDatastoreService();
		ArrayList<Enrollment> enrollments = new ArrayList<Enrollment>();
		// Key key = KeyFactory.createKey("enrollment","enrollment");
		Query query = new Query("Enrollment");

		List<Entity> enrols = d.prepare(query).asList(
				FetchOptions.Builder.withDefaults());

		for (int i = 0; i < enrols.size(); i++) {

			Enrollment e = new Enrollment();
			e.setParentID(Integer.parseInt(""+enrols.get(i).getProperty("parentID")));
			e.setTeacherID(Integer.parseInt(""+enrols.get(i).getProperty("theacherID")));
			e.setStudentID(Integer.parseInt(""+enrols.get(i).getProperty("studentID")));

			// the preferences has to made out of 2 property's because of google
			// restrictions. with no fuhter consiquence to the rest of th
			// program
			ArrayList p = new ArrayList();
			p.add(enrols.get(i).getProperty("days"));
			p.add(enrols.get(i).getProperty("pref"));

			e.setPreferences(p);
			e.setContact((ArrayList<String>) enrols.get(i).getProperty(
					"contact"));

			enrollments.add(e);
		}
		return enrollments;
	}

	/**
	 * Send the list of apponitments to tha datastore as many appointment
	 * Entity's
	 * 
	 * @param a
	 * @return true for success
	 */
	public static boolean sendFinalAppointmentList(ArrayList<Appointment> a) {

		System.out.println(a.size());
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		for (int i = 0; i < a.size(); i++) {
			Entity ea = new Entity("Appointment", a.get(i).getParentID());

			ea.setProperty("parentID", a.get(i).getParentID());
			ea.setProperty("teacherID", a.get(i).getTeacherID());
			ea.setProperty("studentID", a.get(i).getStudentID());
			ea.setProperty("contact", a.get(i).getContact());
			ea.setProperty("tableID", a.get(i).getTableID());
			ea.setProperty("startTime", a.get(i).getStartTime());

			ea.setProperty("date", a.get(i).getDate());
			ea.setProperty("pref", a.get(i).getPref());

			try {
				datastore.put(ea);
			} catch (Exception e) {
				System.out.println("datastore appointment epic fail");
				return false;
			}

		}
		return true;
	}

	public static ArrayList<Appointment> getAppointments() {
		DatastoreService d = DatastoreServiceFactory.getDatastoreService();

		Query q = new Query("Appointment");
		ArrayList<Appointment> al = new ArrayList<Appointment>();

		List<Entity> l = d.prepare(q).asList(
				FetchOptions.Builder.withDefaults());

		for (int i = 0; i < l.size(); i++) {
			Appointment a = new Appointment();
			a.setParentID((((Long) (l.get(i).getProperty("parentID")))
					.intValue()));
			a.setStudentID((((Long) (l.get(i)
					.getProperty("studentID"))).intValue()));
			a.setTeacherID((((Long) (l.get(i)
					.getProperty("teacherID"))).intValue()));

			a.setTableID((((Long) (l.get(i).getProperty("tableID")))
					.intValue()));
			a.setStartTime((((Long) (l.get(i)
					.getProperty("startTime"))).intValue()));
			a.setDate((((Long) (l.get(i).getProperty("date")))
					.intValue()));

			// a.setTableID((Integer)l.get(i).getProperty("tableID"));
			// a.setStartTime((Integer)l.get(i).getProperty("startTime"));
			// a.setDate((Integer)l.get(i).getProperty("date"));
			// a.setPref((String)l.get(i).getProperty("pref"));
			al.add(a);
		}

		return al;
	}

	public static ArrayList<Message> messages = new ArrayList<Message>();

	public static void setMessages(Message msg) {
		messages.add(msg);
	}

	public static void putMessagesInDB() {
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Key messageKey = KeyFactory.createKey("Messages", "Messages");
		Entity messageEntity = new Entity("Message", messageKey);
		messageEntity.setProperty("list", messages);
		ds.put(messageEntity);
	}

	public static ArrayList<Student> getAllStudents() {
		ArrayList<Student> students = new ArrayList<Student>();
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Key studentsKey = KeyFactory.createKey("Students", "Students");
		Query query = new Query("Student", studentsKey);
		List<Entity> list = ds.prepare(query).asList(FetchOptions.Builder.withDefaults());
		for (Entity e : list) {
			try {
				students.add(new Student(Integer.parseInt((String) (e.getProperty("studentId")))));
			} catch (EntityNotFoundException e1) {
				e1.printStackTrace();
			}
		}
		return students;
	}
	
	public static ArrayList<Parent> getAllParents() {
		ArrayList<Parent> parents = new ArrayList<Parent>();
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Key studentsKey = KeyFactory.createKey("Parents", "Parents");
		Query query = new Query("Parent", studentsKey);
		List<Entity> list = ds.prepare(query).asList(FetchOptions.Builder.withDefaults());
		
		for (Entity e : list) {
			try {
				parents.add(new Parent(Integer.parseInt((String)e.getProperty("parentId"))));
			} catch (EntityNotFoundException e1) {
				e1.printStackTrace();
			}
		}
		
		return parents;
	}
}
